const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { pool } = require('../config/db');

// 密钥，实际应用中应该存储在更安全的地方或使用环境变量
const JWT_SECRET = 'aicha_secret_key_2024';
// token过期时间（秒）
const TOKEN_EXPIRE = 60 * 60 * 24 * 7; // 7天

/**
 * 生成token
 * @param {Object} payload - 要加密到token中的数据
 * @param {Number} expiresIn - 过期时间（秒）
 * @return {String} token
 */
function generateToken(payload, expiresIn = TOKEN_EXPIRE) {
  return jwt.sign(payload, JWT_SECRET, { expiresIn });
}

/**
 * 验证token
 * @param {String} token - 要验证的token
 * @return {Object} 验证结果，包含解密后的数据或错误信息
 */
function verifyToken(token) {
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    return {
      valid: true,
      message: '验证成功',
      payload: decoded
    };
  } catch (error) {
    let message = '无效的token';
    if (error.name === 'TokenExpiredError') {
      message = 'token已过期';
    }
    return {
      valid: false,
      message,
      error
    };
  }
}

/**
 * 从请求头中获取token
 * @param {Object} ctx - Koa上下文
 * @return {String|null} token或null
 */
function getTokenFromRequest(ctx) {
  // 优先获取Authorization头，支持不同大小写
  const authHeader = ctx.headers['authorization'] || ctx.headers['Authorization'];
  
  if (authHeader) {
    // 如果是Bearer token格式，则提取token部分
    if (authHeader.startsWith('Bearer ')) {
      return authHeader.slice(7);
    }
    return authHeader;
  }
  
  // 其次尝试获取x-token头
  const xToken = ctx.headers['x-token'] || ctx.headers['X-Token'];
  if (xToken) {
    return xToken;
  }
  
  // 兼容性处理：如果请求体中有token（旧代码可能仍在使用）
  if (ctx.request.body && ctx.request.body.token) {
    return ctx.request.body.token;
  }
  
  return null;
}

/**
 * 密码加密
 * @param {String} password - 原始密码
 * @param {String} salt - 盐值，如果不提供则自动生成
 * @return {Object} 加密结果，包含hash和salt
 */
function encryptPassword(password, salt) {
  // 如果没有提供盐值，则生成一个
  if (!salt) {
    salt = crypto.randomBytes(16).toString('hex');
  }
  
  // 使用sha256算法，迭代1000次
  const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha256').toString('hex');
  
  return {
    hash,
    salt
  };
}

/**
 * 验证密码
 * @param {String} password - 要验证的密码
 * @param {String} hash - 存储的密码哈希
 * @param {String} salt - 存储的盐值
 * @return {Boolean} 验证结果
 */
function verifyPassword(password, hash, salt) {
  const encryptedPassword = encryptPassword(password, salt);
  return encryptedPassword.hash === hash;
}

/**
 * 中间件：验证token并获取用户信息
 * @param {Object} ctx - Koa上下文
 * @param {Function} next - 下一个中间件
 */
async function authMiddleware(ctx, next) {
  const token = getTokenFromRequest(ctx);
  
  if (!token) {
    ctx.status = 401;
    ctx.body = {
      auth: false,
      message: '未提供token',
      code: 401
    };
    return;
  }
  
  const verifyResult = verifyToken(token);
  
  if (!verifyResult.valid) {
    ctx.status = 401;
    ctx.body = {
      auth: false,
      message: verifyResult.message,
      code: 401
    };
    return;
  }
  
  // 从token中获取用户ID
  const userId = verifyResult.payload.userId;
  
  try {
    // 查询用户信息
    const [rows] = await pool.execute(
      'SELECT * FROM users WHERE id = ?',
      [userId]
    );
    
    if (rows.length === 0) {
      ctx.status = 401;
      ctx.body = {
        auth: false,
        message: '用户不存在',
        code: 401
      };
      return;
    }
    
    const user = rows[0];
    
    // 不返回敏感信息
    delete user.password;
    delete user.salt;
    
    // 将用户信息存储在上下文中，以便后续使用
    ctx.state.user = user;
    ctx.state.auth = {
      auth: true,
      message: '验证成功',
      code: 200,
      user
    };
    
    await next();
  } catch (error) {
    ctx.status = 500;
    ctx.body = {
      auth: false,
      message: '验证用户信息失败',
      code: 500,
      error: error.message
    };
  }
}

/**
 * 刷新token
 * @param {String} oldToken - 旧的token
 * @return {Object} 刷新结果，包含新token或错误信息
 */
function refreshToken(oldToken) {
  try {
    // 验证旧token
    const verifyResult = verifyToken(oldToken);
    
    // 如果token完全无效（不是仅仅过期），则返回错误
    if (!verifyResult.valid && verifyResult.error.name !== 'TokenExpiredError') {
      return {
        success: false,
        message: '无效的token',
        error: verifyResult.error
      };
    }
    
    // 从旧token中获取payload（即使token过期，payload依然可以解析）
    const payload = jwt.decode(oldToken);
    if (!payload || !payload.userId) {
      return {
        success: false,
        message: '无效的token payload'
      };
    }
    
    // 生成新token，使用相同的userId
    const newToken = generateToken({
      userId: payload.userId
    });
    
    return {
      success: true,
      message: '刷新成功',
      token: newToken
    };
  } catch (error) {
    return {
      success: false,
      message: '刷新token失败',
      error: error.message
    };
  }
}

module.exports = {
  generateToken,
  verifyToken,
  getTokenFromRequest,
  encryptPassword,
  verifyPassword,
  authMiddleware,
  refreshToken
}; 